#include <assert.h>
#include "widget.h"
#include "widgets.h"
#include "vismgr/view.h"
#include "form_win31.h"

namespace viswidgets
{

// exported widget_base
widget_base::widget_base()
: m_view(NULL)
{
}

widget_base::~widget_base()
{
}

bool widget_base::setshow(bool bshow)
{
	if (!m_view) return false;
	widget* wdgt = reinterpret_cast<widget*>(m_view->data);
	if (!wdgt) return false;
	wdgt->setshow(bshow);
	return true;
}

bool widget_base::setpos(int left, int top, int width, int height)
{
	if (!m_view) return false;
	widget* wdgt = reinterpret_cast<widget*>(m_view->data);
	if (!wdgt) return false;
	wdgt->setpos(left, top, width, height);
	return true;
}

drawing_context::drawing_context(view_draw_reason_e res, view_t* vi, region_t* rgn,
		visgrph::canvas* surface, int dx, int dy, int width, int height)
		: m_view(vi)
		, m_region(rgn)
		, m_canvas(*surface, dx, dy, width, height)
		, m_reason(res)
{
	rect_t r;
	m_canvas.reset_clipping();
	while (!region_getrect(rgn, &r))
		m_canvas.add_clipbox(r.left, r.top, r.width, r.height);
}

view_t* get_root(view_t* vi)
{
	while (vi->parent)
		vi = vi->parent;
	return vi;
}
static visgrph::canvas* surface(view_t* vi)
{
	view_t* root = get_root(vi);//view_find_parent_by_classid(vi, &view_id_root);
	if (NULL == root || NULL == root->data) return NULL;

	visgrph::canvas* cvs;
	// get the canvas
	if (root->desc->style == wstyle_win31)
		cvs = widget_downcast(form_win31_impl, root->data)->canvas();
	// else: todo

	return cvs;
}

// static handler
void widget::widget_draw_handler(view_draw_reason_e res, view_t* vi, region_t* rgn)
{
	visgrph::canvas* cvs = surface(vi);
	assert(NULL != cvs);

	int dx, dy;
	view_get_delta_pos(vi, NULL, &dx, &dy);

	// todo: check
	dx += vi->left;
	dy += vi->top;

	int width = cvs->width();
	if (vi->width < width - dx) width = vi->width;
	int height = cvs->height();
	if (vi->height < height - dy) height = vi->height;

	// create the drawing context
	drawing_context dc(res, vi, rgn, cvs, dx, dy, width, height);
	reinterpret_cast<widget*>(vi->data)->on_draw(dc);
}

void widget::widget_event_handler(view_event_type_e type, view_t* vi, void* data)
{
	reinterpret_cast<widget*>(vi->data)->on_event(type, data);
}

widget::widget(view_desc_t* desc, view_t* vi)
{
	assert(NULL != desc);
	m_view = view_create(vi, desc, this);
}

widget::widget(int left, int top, int width, int height,
	view_desc_t* desc, view_t* vi)
{
	assert(NULL != desc);
	m_view = view_create(vi, desc, this);
	if (m_view)
		view_setpos(m_view, left, top, width, height);
}

// setshow
// set if the widget shall show or not
void widget::setshow(bool bshow)
{
	view_setshow(m_view, (_bool)bshow);
}

// set position
void widget::setpos(int left, int top, int width, int height)
{
	view_setpos(m_view, left, top, width, height);
}

void widget::on_draw(drawing_context& dc)
{
	// do nothing
}

void widget::on_event(view_event_type_e type, void* data)
{
	// do nothing
}

}; // namespace viswidgets
/* EOF */
